#include "Object.hpp"

#ifndef __COLLISION_ENGINE_HPP__
#define __COLLISION_ENGINE_HPP__

class CollidableObject {
	protected:
		/** pointer to an updated hitboxes */
		HitBoxes* m_updatedHitBoxes;

		/** iterator of this object corresponding to the position
		  * of this object in the collidable list */
		list<CollidableObject*>::iterator m_iterator;

		/** pointer to the collidable object that launch this one
		  * in case where this object is a projectile */
		CollidableObject* m_launcher;

	public:
		/** virtual function called by the instancied object to
		  * update his hitboxes */
		virtual void updateHitBoxes() = 0;

		/** defining the iterator corresponding to this object */
		void setIterator(list<CollidableObject*>::iterator it) { m_iterator = it;};

		/** function that is called in case of a collision with an other Collidable Object 
		 *	param[in] obj object which whom a collision has happened
		 */
		virtual void collisionCallBack(CollidableObject* obj) = 0;

		/** projectile could collide ground */
		virtual void groundCollisionCallBack(string type) { return;};

		/** retrieving this object iterator */
		list<CollidableObject*>::iterator getIterator() { return m_iterator;};

		/** get pointer to hitboxes updated with the current location of the
		 * collidable object
		 * return pointer hitboxes
		 */
		virtual HitBoxes* getUpdatedHitBoxes() {
			return m_updatedHitBoxes;
		};

		/** in case where this CollidableObject is a projectile, this function 
		 *  has to be used to defined the launcher of the projectile
		 *  (no possible collision between a launcher and its projectile 
		 *  param[in] obj launcher to be registered
		 */ 
		void setLauncher(CollidableObject* obj) { m_launcher = obj;};

		/** function to get launcher in case of a Projectile */
		CollidableObject* getLauncher() { return m_launcher;};
};


class CollisionEngine {
  protected:
	/** list of pointer to projectiles (object that herited from CollidableObject) */
    static list<CollidableObject*> m_projectiles;

	/** list of pointer to objects ( object that herited from CollidableObject) */
    static list<CollidableObject*> m_objects;
  public:
	/** function to delete a projectile from the list, by giving 
	  * this function a pointer to the corresponding object 
	  * that contains an iterator to the position of this object
	  * on the projectile list */
	static list<CollidableObject*>::iterator deleteProjectile(CollidableObject* co) {
		return m_projectiles.erase(co->getIterator());
	};

	/** function for update Collision, updating CollidableObject and then
	  * computing collision and calling back */
    static void update();

	/** function for adding an object pointer to the Collision
	  *  Engine object list */
	static void addObject(CollidableObject* co) {
		co->setIterator(m_objects.insert(m_objects.end(), co));
	}

	/** function for adding a projectile pointer to the Collision 
	  * Engine projectile list */
	static void addProjectile(CollidableObject* co) {
		co->setIterator(m_projectiles.insert(m_projectiles.end(), co));
	}
};

#endif
